#include <algorithm>
#include <iostream>
using namespace std;

const int MAXN = 10010;
int coins[MAXN];             // 存储硬币面值
int n, m;                    // 硬币数量和目标金额
int current_solution[MAXN];  // 当前搜索路径上的硬币
int best_solution[MAXN];     // 最优解（字典序最小）
int current_count = 0;       // 当前路径上的硬币数量
int best_count = 0;          // 最优解中的硬币数量
bool found = false;          // 是否找到了解
int suffix_sum[MAXN];        // 后缀和数组，用于剪枝

// DFS搜索函数
// index: 当前考虑的硬币索引
// current_sum: 当前路径上硬币面值之和
void dfs(int index, int current_sum) {
  // 如果已经找到解，则直接返回，因为我们按顺序搜索，第一个解就是最优的
  if (found) {
    return;
  }

  // 如果当前和等于目标金额，找到一个解
  if (current_sum == m) {
    found = true;
    best_count = current_count;
    for (int i = 0; i < current_count; i++) {
      best_solution[i] = current_solution[i];
    }
    return;
  }

  // 剪枝：如果索引越界或当前和已经超过目标金额
  if (index >= n || current_sum > m) {
    return;
  }

  // 剪枝：如果即使加上后面所有硬币也无法达到目标金额
  if (current_sum + suffix_sum[index] < m) {
    return;
  }

  // 选择当前硬币
  current_solution[current_count] = coins[index];
  current_count++;
  dfs(index + 1, current_sum + coins[index]);
  current_count--;  // 回溯

  // 不选择当前硬币
  dfs(index + 1, current_sum);
}

void Q3() {
  cin >> n >> m;

  for (int i = 0; i < n; i++) {
    cin >> coins[i];
  }

  // 1. 排序硬币面值
  sort(coins, coins + n);

  // 2. 计算后缀和，用于剪枝
  suffix_sum[n] = 0;
  for (int i = n - 1; i >= 0; i--) {
    suffix_sum[i] = suffix_sum[i + 1] + coins[i];
  }

  // 3. 初始化变量
  current_count = 0;
  best_count = 0;
  found = false;

  // 4. 开始DFS搜索
  dfs(0, 0);

  // 5. 输出结果
  if (found) {
    for (int i = 0; i < best_count; i++) {
      if (i > 0)
        cout << " ";
      cout << best_solution[i];
    }
    cout << endl;
  } else {
    cout << "No Solution" << endl;
  }
}

int main() {
  Q3();
  return 0;
}